﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Elderos.Highlight.Search;
using Elderos.Ontology;

namespace Elderos.Highlight.Rules
{
    public abstract class RuleTypeDefaultWeight : RankingRule
    {
        protected RuleTypeDefaultWeight(IOntologyData ontology, params string[] typenames) : base(ontology)
        {
            _typenames = new HashSet<string>(typenames);
        }



        private readonly HashSet<string> _typenames;

        protected HashSet<int> TypeIDs { get; set; }

        public async override Task Initialize(List<Func<HighlightResult, Task>> articleCacheInit)
        {
            await base.Initialize(articleCacheInit);

            TypeIDs = new HashSet<int>(Ontology.Types
                .Where(x => _typenames.Contains(x.Name))
                .Select(x => x.ID));

            articleCacheInit.Add(async highlightResult => 
                    {
                        int[] entityIDs = highlightResult.Positions
                                                         .SelectMany(x => x.EntitiesFlattened)
                                                         .Select(x => x.EntityID)
                                                         .Distinct()
                                                         .ToArray();

                        var entityFbTypes = await Ontology.GetEntityFBTypesAsync(entityIDs);
                        highlightResult.ArticleCache.Add(this, entityFbTypes);
                    });
        }

#pragma warning disable 1998
        protected override async Task<Dictionary<TextEntity, IRuleResult>> InnerRank(HighlightResult highlightResult)
#pragma warning restore 1998
        {
            var results = new Dictionary<TextEntity, IRuleResult>();
            
            Dictionary<int, List<int>> entityTypes = ((List<EntityFBType>) highlightResult.ArticleCache[this])
                .Where(x => TypeIDs.Contains(x.FBTypeID))
                .GroupBy(x => x.EntityID)
                .ToDictionary(x => x.Key, x => new List<int>(x.Select(y => y.FBTypeID)));


            foreach (var textEntity in highlightResult.Positions.SelectMany(x => x.EntitiesFlattened))
            {
                if (!entityTypes.ContainsKey(textEntity.EntityID) ||
                    !entityTypes[textEntity.EntityID].Any(x => TypeIDs.Contains(x)))
                    continue;

                results.Add(textEntity, new BinomialResult(Name, true));
            }

            return results;
        }

        public override IRuleResult EmptyResult
        {
            get { return new BinomialResult(Name, false);}
        }
    }
}
